import { springLog, spring, Clazz } from 'j-spring';
import { EntityManager, QueryRunner, DataSource } from 'typeorm';
import { AsyncLocalStorage } from 'node:async_hooks';

export class SpringTxManager {
  //唯一异步事务标记存储器
  txLocalStorage = new AsyncLocalStorage();
  //异步事务标识
  TX_INDEx = 0;
  //事务容器
  TX_MAP: Map<number, EntityManager> = new Map();

  /**
   * 注册容器，并获取事务的编号
   * */
  registerEntityManager(): number {
    const tIndex = this.TX_INDEx++;
    this.TX_MAP.set(tIndex, this.createEntityManager());
    return tIndex;
  }

  async startTx(id: number) {
    springLog.verbose(`连接池${id}: 申请成功`);
    await this.TX_MAP.get(id)?.queryRunner?.startTransaction();
  }
  async rollbackTx(id: number) {
    springLog.verbose(`连接池${id}: 回滚事务`);
    await this.TX_MAP.get(id)?.queryRunner?.rollbackTransaction();
  }
  async cmmitTx(id: number) {
    springLog.verbose(`连接池${id}: 提交事务`);
    await this.TX_MAP.get(id)?.queryRunner?.commitTransaction();
  }
  async release(id: number) {
    springLog.verbose(`连接池${id}:释放`);
    await this.TX_MAP.get(id)?.queryRunner?.release();
    this.TX_MAP.delete(id);
  }

  //创建事务
  createEntityManager(): EntityManager {
    const dataSource = spring.getBeanFromContainer(DataSource as Clazz);
    if (!dataSource) {
      throw `spring容器中未找到DataSource实例`;
    }
    const queryRunner: QueryRunner = dataSource.createQueryRunner();
    const manager: EntityManager = queryRunner.manager;
    return manager;
  }

  //获取当前事务管理
  getCurrentEntityManager(): EntityManager {
    const txId = this.txLocalStorage.getStore();
    if (txId === undefined) {
      throw `当前闭包不存在事务ID,请检查是否启用了@Serivce或@Transactional注解`;
    }
    const e = this.TX_MAP.get(Number(txId));
    if (!e) {
      throw `事务管理器不存在! id:${txId}`;
    }
    return e;
  }
}
